#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
目录团队分配工具

基于团队名称、描述以及目录路径的智能匹配算法，为directories表中的目录分配责任团队。
"""

import os
import sqlite3
import re
from typing import Dict, List, Tuple, Optional
from datetime import datetime
import logging

# 配置日志
logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s')
logger = logging.getLogger(__name__)

class DirectoryTeamAssigner:
    """目录团队分配器"""

    def __init__(self, db_path: str = None):
        """初始化分配器"""
        if db_path is None:
            # 默认数据库路径
            current_dir = os.path.dirname(os.path.abspath(__file__))
            project_root = os.path.dirname(os.path.dirname(current_dir))
            db_path = os.path.join(project_root, 'backend', 'data', 'uma_insight.db')

        self.db_path = db_path
        self.teams = []
        self.weight_config = {
            'exact_match': 100,      # 完全匹配权重
            'path_keyword': 90,      # 路径关键词权重
            'description_keyword': 80, # 描述关键词权重
            'partial_match': 60,     # 部分匹配权重
            'hierarchical': 40       # 层级匹配权重
        }

        # 技术关键词映射
        self.keyword_mapping = {
            'security': [
                'security', '安全', 'privacy', '隐私', 'safe', 'protect',
                'authentication', 'authorization', 'auth', '证书', '加密'
            ],
            'rendering': [
                'render', '渲染', 'compositor', 'paint', 'webgl', 'canvas',
                'graphics', 'gpu', 'drawing', '动画', '视觉效果'
            ],
            'network': [
                'network', '网络', 'http', 'socket', 'net', 'connect',
                'protocol', 'tcp', 'udp', 'websocket', 'fetch', 'xhr'
            ],
            'media': [
                'media', '视频', '音频', 'camera', 'video', 'audio',
                'multimedia', 'playback', 'streaming', 'codec', '编解码'
            ],
            'storage': [
                'storage', '存储', 'database', 'cache', 'local', 'session',
                'indexdb', 'localStorage', 'sql', 'persistence'
            ],
            'input': [
                'input', '输入', 'event', 'gesture', 'touch', 'keyboard',
                'mouse', 'interaction', '交互', 'focus', 'click'
            ],
            'browser': [
                'browser', '浏览器', 'web', 'page', 'tab', 'navigation',
                'history', 'bookmark', 'cookie', 'javascript'
            ],
            'system': [
                'system', '系统', 'os', 'platform', 'process', 'thread',
                'memory', 'cpu', 'performance', 'optimization'
            ],
            'extension': [
                'extension', '扩展', 'plugin', 'addon', 'module', 'component'
            ]
        }

    def connect_database(self) -> sqlite3.Connection:
        """连接数据库"""
        try:
            conn = sqlite3.connect(self.db_path)
            conn.row_factory = sqlite3.Row
            return conn
        except Exception as e:
            logger.error(f"连接数据库失败: {e}")
            raise

    def load_teams(self) -> List[Dict]:
        """加载团队信息"""
        conn = self.connect_database()
        try:
            cursor = conn.cursor()
            cursor.execute("""
                SELECT id, name, description
                FROM teams
                ORDER BY name
            """)

            teams = []
            for row in cursor.fetchall():
                teams.append({
                    'id': row['id'],
                    'name': row['name'],
                    'description': row['description'] or '',
                    'keywords': self._extract_keywords(row['name'], row['description'])
                })

            logger.info(f"加载了 {len(teams)} 个团队信息")
            return teams

        finally:
            conn.close()

    def _extract_keywords(self, name: str, description: str) -> List[str]:
        """从团队名称和描述中提取关键词"""
        text = f"{name} {description}".lower()
        keywords = []

        # 添加团队名称作为关键词
        keywords.extend(name.lower().split())

        # 从描述中提取关键词
        if description:
            # 使用正则表达式提取中文和英文词汇
            words = re.findall(r'[a-zA-Z]+|[\u4e00-\u9fff]+', description.lower())
            keywords.extend(words)

        # 去重并过滤太短的词
        return list(set([kw for kw in keywords if len(kw) >= 2]))

    def load_directories(self) -> List[Dict]:
        """加载目录信息"""
        conn = self.connect_database()
        try:
            cursor = conn.cursor()
            cursor.execute("""
                SELECT id, path, name
                FROM directories
                ORDER BY path
            """)

            directories = []
            for row in cursor.fetchall():
                directories.append({
                    'id': row['id'],
                    'path': row['path'],
                    'name': row['name'],
                    'path_parts': row['path'].split('/')
                })

            return directories

        finally:
            conn.close()

    def calculate_match_score(self, directory: Dict, team: Dict) -> Tuple[int, str]:
        """计算目录与团队的匹配分数"""
        max_score = 0
        best_match_method = ''

        dir_name = directory['name'].lower()
        dir_path = directory['path'].lower()
        dir_parts = directory['path_parts']

        # 1. 目录名完全匹配
        if dir_name == team['name'].lower():
            score = self.weight_config['exact_match']
            if score > max_score:
                max_score = score
                best_match_method = f"目录名完全匹配: {dir_name}"

        # 2. 团队关键词在路径中的匹配
        for keyword in team['keywords']:
            if keyword in dir_path and len(keyword) >= 3:
                score = self.weight_config['path_keyword']
                if keyword in dir_name:
                    score += 10  # 在目录名中的额外加分
                if score > max_score:
                    max_score = score
                    best_match_method = f"路径关键词匹配: {keyword}"

        # 3. 技术领域关键词匹配
        for tech_domain, tech_keywords in self.keyword_mapping.items():
            if any(kw in dir_path for kw in tech_keywords):
                # 检查团队是否属于这个技术领域
                team_text = f"{team['name']} {team['description']}".lower()
                if any(kw in team_text for kw in tech_keywords):
                    score = self.weight_config['description_keyword']
                    if score > max_score:
                        max_score = score
                        matched_keywords = [kw for kw in tech_keywords if kw in team_text]
                        best_match_method = f"技术领域匹配: {tech_domain} ({matched_keywords[:2]})"

        # 4. 部分匹配
        for keyword in team['keywords']:
            if len(keyword) >= 4 and keyword in dir_name:
                score = self.weight_config['partial_match']
                if score > max_score:
                    max_score = score
                    best_match_method = f"部分匹配: {keyword}"

        # 5. 层级匹配（目录结构相似性）
        for part in dir_parts:
            if part in team['keywords'] and len(part) >= 3:
                score = self.weight_config['hierarchical']
                if score > max_score:
                    max_score = score
                    best_match_method = f"层级匹配: {part}"

        return max_score, best_match_method

    def assign_team_to_directory(self, directory: Dict) -> Optional[Dict]:
        """为单个目录分配团队"""
        best_team = None
        best_score = 0
        best_method = ''

        for team in self.teams:
            score, method = self.calculate_match_score(directory, team)

            if score > best_score:
                best_score = score
                best_team = team
                best_method = method

        # 设置最低分数阈值
        min_threshold = 40

        if best_score >= min_threshold:
            return {
                'team_id': best_team['id'],
                'team_name': best_team['name'],
                'confidence': best_score,
                'method': best_method
            }
        else:
            return None

    def update_database(self, assignments: List[Dict]):
        """更新数据库中的分配结果"""
        conn = self.connect_database()
        try:
            cursor = conn.cursor()

            for assignment in assignments:
                cursor.execute("""
                    UPDATE directories
                    SET team_id = ?,
                        assignment_confidence = ?,
                        assigned_at = CURRENT_TIMESTAMP,
                        assignment_method = ?
                    WHERE id = ?
                """, (
                    assignment['team_id'],
                    assignment['confidence'],
                    assignment['method'],
                    assignment['directory_id']
                ))

            conn.commit()
            logger.info(f"成功更新了 {len(assignments)} 个目录的团队分配")

        except Exception as e:
            conn.rollback()
            logger.error(f"更新数据库失败: {e}")
            raise
        finally:
            conn.close()

    def run_assignment(self):
        """执行完整的分配流程"""
        logger.info("开始目录团队分配流程")

        # 加载数据
        self.teams = self.load_teams()
        directories = self.load_directories()

        logger.info(f"开始处理 {len(directories)} 个目录的团队分配...")

        assignments = []
        unassigned_count = 0

        for directory in directories:
            result = self.assign_team_to_directory(directory)

            if result:
                assignments.append({
                    'directory_id': directory['id'],
                    'directory_path': directory['path'],
                    'directory_name': directory['name'],
                    **result
                })
            else:
                unassigned_count += 1
                logger.warning(f"未找到匹配团队: {directory['path']}")

        # 更新数据库
        if assignments:
            self.update_database(assignments)

        # 统计结果
        total_dirs = len(directories)
        assigned_dirs = len(assignments)
        coverage_rate = (assigned_dirs / total_dirs) * 100 if total_dirs > 0 else 0
        avg_confidence = sum(a['confidence'] for a in assignments) / assigned_dirs if assigned_dirs > 0 else 0

        logger.info("目录分配完成！")
        logger.info(f"成功分配: {assigned_dirs}个 ({coverage_rate:.2f}%)")
        logger.info(f"未分配: {unassigned_count}个 ({(unassigned_count/total_dirs)*100:.2f}%)")
        logger.info(f"平均置信度: {avg_confidence:.1f}")

        # 输出团队分配统计
        team_stats = {}
        for assignment in assignments:
            team_name = assignment['team_name']
            if team_name not in team_stats:
                team_stats[team_name] = []
            team_stats[team_name].append(assignment)

        logger.info("\n=== 团队分配统计 ===")
        for team_name, team_assignments in sorted(team_stats.items(), key=lambda x: len(x[1]), reverse=True):
            count = len(team_assignments)
            avg_conf = sum(a['confidence'] for a in team_assignments) / count
            logger.info(f"{team_name}: {count}个目录 (平均置信度: {avg_conf:.1f})")

        return {
            'total_directories': total_dirs,
            'assigned_directories': assigned_dirs,
            'unassigned_directories': unassigned_count,
            'coverage_rate': coverage_rate,
            'average_confidence': avg_confidence,
            'team_assignments': team_stats
        }


def main():
    """主函数"""
    import argparse

    parser = argparse.ArgumentParser(description='目录团队分配工具')
    parser.add_argument('--db-path', help='数据库文件路径')
    parser.add_argument('--min-confidence', type=int, default=40,
                       help='最低置信度阈值 (默认: 40)')
    parser.add_argument('--dry-run', action='store_true',
                       help='试运行模式，不更新数据库')

    args = parser.parse_args()

    try:
        assigner = DirectoryTeamAssigner(args.db_path)
        assigner.weight_config['min_threshold'] = args.min_confidence

        if args.dry_run:
            logger.info("=== 试运行模式，不会更新数据库 ===")
            # 在试运行模式下，我们可以加载数据但不执行更新
            # 这里可以添加更多的试运行逻辑

        result = assigner.run_assignment()

        logger.info("\n=== 分配任务完成 ===")
        logger.info(f"覆盖率: {result['coverage_rate']:.2f}%")
        logger.info(f"平均置信度: {result['average_confidence']:.1f}")

    except Exception as e:
        logger.error(f"分配过程出错: {e}")
        return 1

    return 0


if __name__ == "__main__":
    exit(main())